/*****************************************************************************
 * Copyright (c) 2011 CEA LIST.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *
 *		CEA LIST - Initial API and implementation
 *
 *****************************************************************************/
package org.eclipse.papyrus.uml.diagram.common.locator;

import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Rectangle;

/**
 * <pre>
 * This class provides convenience methods to manage Port location.
 *
 * The method are base on the Port and its graphical parent bounds (given as Rectangle), which can either be
 * based on the figure bounds or the view bounds.
 * </pre>
 */
public class PortPositionLocatorUtils {

	/**
	 * Get the valid border location of the Port with the proposed location on
	 * the parent.
	 *
	 * @param parentFigureBounds
	 *            the parent bounds.
	 * @param proposedFigureBounds
	 *            the proposed Port bounds.
	 * @param borderItemOffset
	 *            the overlapping size of the Port over its parent figure.
	 * @return the allowed bounds for the Port (location relative to parent
	 *         TopLeft point).
	 */
	public static Rectangle getBorderLocation(Rectangle parentFigureBounds, Rectangle proposedFigureBounds, int borderItemOffset) {

		// Initialize port location with proposed location
		// and resolve the bounds of it graphical parent
		Rectangle realLocation = proposedFigureBounds.getCopy();

		Rectangle parentRec = parentFigureBounds.getCopy();

		// Calculate Max position around the graphical parent (1/2 size or the
		// port around
		// the graphical parent bounds.
		int xMin = -borderItemOffset;
		int xMax = -borderItemOffset + parentRec.width;
		int yMin = -borderItemOffset;
		int yMax = -borderItemOffset + parentRec.height;

		// Modify Port location if MAX X or Y are exceeded
		if (realLocation.x < xMin) {
			realLocation.x = xMin;
		}

		if (realLocation.x > xMax) {
			realLocation.x = xMax;
		}

		if (realLocation.y < yMin) {
			realLocation.y = yMin;
		}

		if (realLocation.y > yMax) {
			realLocation.y = yMax;
		}

		// Ensure the port is positioned on its parent borders and not in the
		// middle.
		// Modify position if needed.
		if ((realLocation.y != yMin) && (realLocation.y != yMax)) {
			if ((realLocation.x != xMin) && (realLocation.x != xMax)) {

				if (realLocation.x <= (xMin + (parentRec.width / 2))) {
					realLocation.x = xMin;
				} else {
					realLocation.x = xMax;
				}
			}
		}

		// Return constrained location
		return realLocation;
	}

	/**
	 * Get the current side (on the parent) where the Port is located.
	 *
	 * @param parentFigureBounds
	 *            the parent bounds.
	 * @param proposedFigureBounds
	 *            the proposed Port bounds.
	 * @param borderItemOffset
	 *            the overlapping size of the Port over its parent figure.
	 *
	 * @return the position of the port around its parent. This position can be
	 *         <ul>
	 *         <li>{@linkplain PositionConstants#NORTH}</li>
	 *         <li>{@linkplain PositionConstants#SOUTH}</li>
	 *         <li>{@linkplain PositionConstants#EAST}</li>
	 *         <li>{@linkplain PositionConstants#WEST}</li>
	 *         <li>{@linkplain PositionConstants#NORTH_EAST}</li>
	 *         <li>{@linkplain PositionConstants#NORTH_WEST}</li>
	 *         <li>{@linkplain PositionConstants#SOUTH_EAST}</li>
	 *         <li>{@linkplain PositionConstants#SOUTH_WEST}</li>
	 *         </ul>
	 */
	public static int getCurrentSideOfParent(Rectangle parentFigureBounds, Rectangle figureBounds, int borderItemOffset) {
		int position = PositionConstants.NONE;

		// we are not on EAST, not on WEST, but we are on the NORTH
		if ((figureBounds.x != parentFigureBounds.width - borderItemOffset) && (figureBounds.x != -borderItemOffset) && (figureBounds.y == -borderItemOffset)) {
			position = PositionConstants.NORTH;

			// we are not on the EAST and not on the WEST, but we are on the
			// SOUTH
		} else if ((figureBounds.x != parentFigureBounds.width - borderItemOffset) && (figureBounds.x != -borderItemOffset) && (figureBounds.y == parentFigureBounds.height - borderItemOffset)) {
			position = PositionConstants.SOUTH;

			// we are on the EAST, but we are not on the NORTH and not on the
			// SOUTH
		} else if ((figureBounds.x == parentFigureBounds.width - borderItemOffset) && (figureBounds.y != -borderItemOffset) && (figureBounds.y != parentFigureBounds.height - borderItemOffset)) {
			position = PositionConstants.EAST;

			// we are on the WEST, but we are not on the on the NORTH and not on
			// the SOUTH
		} else if ((figureBounds.x == -borderItemOffset) && (figureBounds.y != -borderItemOffset) && (figureBounds.y != parentFigureBounds.height - borderItemOffset)) {
			position = PositionConstants.WEST;

			// we are on the NORTH and on the EAST
		} else if ((figureBounds.x == parentFigureBounds.width - borderItemOffset) && (figureBounds.y == -borderItemOffset)) {
			position = PositionConstants.NORTH_EAST;

			// we are on the NORTH and on the WEST
		} else if ((figureBounds.x == -borderItemOffset) && (figureBounds.y == -borderItemOffset)) {
			position = PositionConstants.NORTH_WEST;

			// we are on the EAST and on the SOUTH
		} else if ((figureBounds.x == parentFigureBounds.width - borderItemOffset) && (figureBounds.y == parentFigureBounds.height - borderItemOffset)) {
			position = PositionConstants.SOUTH_EAST;

			// we are on the WEST and on the SOUTH
		} else if ((figureBounds.x == -borderItemOffset) && (figureBounds.y == parentFigureBounds.height - borderItemOffset)) {
			position = PositionConstants.SOUTH_WEST;
		}

		return position;
	}

}
